import os
import webbrowser

import json
from datetime import datetime

from flask import Flask, request, send_from_directory

from db.StudentDB import StudentDB
from utils.AesUtils import AesUtils
from utils.ApiClient import ApiClient
from utils.ResponseUtils import ResponseUtils
from django.db import transaction

import logging

app = Flask(__name__)

# 前端静态文件路径
FRONTEND_FOLDER = os.path.join(os.path.dirname(__file__), 'dist')

# 获取当前日期作为日志文件名
current_date = datetime.now().strftime("%Y-%m-%d")
log_filename = f"logs/outlog_{current_date}.log"  # 存放在 logs/ 目录下

# 确保 logs 目录存在
import os
os.makedirs("logs", exist_ok=True)

# 配置日志记录
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler(log_filename, encoding='utf-8'),
        logging.StreamHandler()  # 同时输出到控制台
    ]
)

@app.route('/')
def index():
    return send_from_directory(FRONTEND_FOLDER, 'index.html')

@app.route('/<path:filename>')
def serve_static(filename):
    return send_from_directory(FRONTEND_FOLDER, filename)




code200 = 200
code1 = 1

@app.route('/api/students/list', methods=['GET'])
def get_list():
    # 1. 获取并验证参数
    schoolName = request.args.get('schoolName', type=str)
    studentCode = request.args.get('studentCode', type=str)
    idCard = request.args.get('idCard', type=str)
    itemName = request.args.get('itemName', type=str)
    gender = request.args.get('gender', type=str)
    groupNo = request.args.get('groupNo', type=str)
    status = request.args.get('status', type=str)
    page_num = request.args.get('pageNum', default=1, type=int)
    page_size = request.args.get('pageSize', default=50, type=int)
    if page_num < 1 or page_size < 1:
        raise ValueError("分页参数必须大于0")
    studentsDB = StudentDB()
    list = studentsDB.search_students_with_pagination(
        {"schoolName": schoolName, "studentCode": studentCode, "idCard": idCard, "itemName": itemName, "gender": gender,
         "groupNo": groupNo, "status": status}, page_num, page_size)
    # 使用示例
    return ResponseUtils.build_response(code200, "success", "数据查询成功", list[0], list[1])


@app.route('/api/students/delete_all', methods=['DELETE'])
def delete_all():
    studentsDB = StudentDB()
    bol = studentsDB.delete_all_student()
    if (bol):
        return ResponseUtils.build_response(code200, "success", "清空成功")
    else:
        return ResponseUtils.build_response(code200, "success", "清空失败")


@transaction.atomic
@app.route('/api/students/get/list', methods=['GET'])
def get_api_list():
    # 清空考生数据
    delete_all()

    # 调用接口获取考生数据
    # 创建 API 客户端实例
    # api = ApiClient(config_file="/config/apiconfig.ini")
    api = ApiClient()

    # GET 请求示例
    print("=== GET 请求示例 获取访问令牌 ===")
    api._authenticate()
    logging.info(f"siteCode：" + str(api.siteCode))
    logging.info(f"siteName：" + str(api.siteName))
    logging.info(f"type：" + str(api.type))
    logging.info(f"encryptKey：" + str(api.encryptKey))
    logging.info(f"token：" + str(api.token))
    logging.info(f"typeValue：" + str(api.typeValue))
    print(f"siteCode：" + str(api.siteCode))
    print(f"siteName：" + str(api.siteName))
    print(f"type：" + str(api.type))
    print(f"encryptKey：" + str(api.encryptKey))
    print(f"token：" + str(api.token))
    print(f"typeValue：" + str(api.typeValue))

    studentCond = 1
    while studentCond > 0:
        # POST 请求示例
        print("\n=== POST 请求示例 考生信息下载 ===")
        logging.info("\n=== POST 请求示例 考生信息下载 ===")
        response = api.post(
            api.base_url,
            api.student_url,
            json_data={
                "data": {
                    "itemCode": "",
                    "pageNo": studentCond
                },
                "msEquipment": "",
                "requestTime": 0,
                "encrypt": "0",
                "version": "1.0.0",
                "lastUpdateTime": "",
            },
            headers={
                "Authorization": "Bearer " + api.token
            }
        )
        print(response)
        logging.info(response)
        print(response.get("data"))
        logging.info(response.get("data"))
        if 1 == response.get("code"):
            error_msg = f"考生信息查询失败: {response.code} - {response.msg}"
            api.logger.error(error_msg)
            return ResponseUtils.build_response(-1, "erroe", "考生信息查询失败:" + error_msg)
            # raise ApiRequestError(error_msg, response=response)
        studentData = response.get("data")
        # 创建 AES 加密器
        encryptKey = api.encryptKey.encode('utf-8')
        aes = AesUtils(encryptKey)
        print("考生加密信息:", studentData)
        logging.info("考生加密信息:", studentData)
        # 解密（输入 HEX）
        decrypted_text = aes.decrypt(studentData)
        data = json.loads(decrypted_text)
        if "studentList" in data and isinstance(data["studentList"], list):
            studentCond = studentCond + 1
            # 批量插入
            process_student_data(decrypted_text)
        else:
            studentCond = 0
            print("未找到有效的studentList，流程结束")
            logging.info("未找到有效的studentList，流程结束")
        print("解密结果:", data)
        logging.info("解密结果:", data)
    # studentsDB = StudentDB()
    # students = studentsDB.search_students({}, 50)
    # 使用示例
    return ResponseUtils.build_response(code200, "success", "同步成功")


def process_student_data(json_data):
    """处理学生数据的主函数"""
    try:
        # 1. 解析JSON字符串
        data = json.loads(json_data)
        print("解密结果:", data)
        logging.info("解密结果:", data)

        # 2. 检查studentList是否存在且非空
        if "studentList" in data and isinstance(data["studentList"], list):
            print("检测到studentList，开始批量插入...")
            logging.info("检测到studentList，开始批量插入...")
            studentsDB = StudentDB()
            studentsDB.insert_students_batch(data["studentList"])
            print("插入完成")
            logging.info("插入完成")
        else:
            print("未找到有效的studentList，流程结束")
            logging.info("未找到有效的studentList，流程结束")

    except json.JSONDecodeError:
        print("错误：无效的JSON格式")
        logging.error("错误：无效的JSON格式")
    except Exception as e:
        print(f"处理过程中发生错误：{str(e)}")
        logging.info(f"处理过程中发生错误：{str(e)}")


# 获取云平台未同步的考生列表信息
@app.route('/api/exam/cloud/student/list', methods=['GET'])
def get_exam_cloud_student_list():
    print("云平台接口调用开始")
    logging.info("云平台接口调用开始")
    # api = ApiClient(config_file="/config/apiconfig.ini")
    api = ApiClient()
    try:
        zkh = request.args.get('zkh', type=str)
        jdh = request.args.get('jdh', type=str)
        zxmc = request.args.get('zxmc', type=str)
        sfzh = request.args.get('sfzh', type=str)
        xcxm = request.args.get('xcxm', type=str)
        pageNum = request.args.get('pageNum', default=1, type=int)
        pageSize = request.args.get('pageSize', default=50, type=int)
        headers = {
            "Content-Type": "application/x-www-form-urlencoded"
        }
        params = {
            "zkh": zkh,
            "jdh": jdh,
            "zxmc": zxmc,
            "sfzh": sfzh,
            "xcxm": xcxm,
            "pageNum": pageNum,
            "pageSize": pageSize
        }
        response = api.post(
            api.cloud_url,
            api.fpl_student_url,
            json_data=params
        )
        print(response)
        logging.info(response)
        print(response.get("code"))
        logging.info(response.get("code"))
        print(response.get("data"))
        logging.info(response.get("data"))
        if (code200 == response.get("code")):
            data = response.get("data")
            print(data)
            logging.info(data)
            rows = data.get("rows")
            print(rows)
            logging.info(rows)
            total = data.get("total")
            print(total)
            logging.info(total)
            return response
        else:
            return ResponseUtils.build_response(code1, "error", response.get("msg"))
    except Exception as e:
        print(f"云平台接口调用过程中发生错误: {str(e)}")
        logging.error(f"云平台接口调用过程中发生错误: {str(e)}")
        raise


# 同步平台成绩至本地
@app.route('/api/sync/cloud/result/local', methods=['POST'])
def sync_cloud_result_local():
    print("云平台接口调用开始")
    logging.info("云平台接口调用开始")
    # api = ApiClient(config_file="/config/apiconfig.ini")
    api = ApiClient()
    try:
        # zkh = request.args.get('zkh', type=str)
        # jdh = request.args.get('jdh', type=str)
        # zxmc = request.args.get('zxmc', type=str)
        # sfzh = request.args.get('sfzh', type=str)
        # xcxm = request.args.get('xcxm', type=str)
        # pageNum = request.args.get('pageNum', default=1, type=int)
        # pageSize = request.args.get('pageSize', default=50, type=int)

        # 获取 JSON 请求体
        data = request.get_json()
        if not data:
            return ResponseUtils.build_response(code1, "error", "请求体必须为JSON格式")

        # 从 JSON 中提取参数
        zkh = data.get('zkh')
        zkhs = data.get('zkhs')
        jdh = data.get('jdh')
        zxmc = data.get('zxmc')
        sfzh = data.get('sfzh')
        xcxm = data.get('xcxm')
        pageNum = data.get('pageNum', 1)
        pageSize = data.get('pageSize', 50)

        headers = {
            "Content-Type": "application/x-www-form-urlencoded"
        }

        dataJson = {
            "zkh": zkh,
            "zkhs": zkhs,
            "jdh": jdh,
            "zxmc": zxmc,
            "sfzh": sfzh,
            "xcxm": xcxm,
            "pageNum": pageNum,
            "pageSize": pageSize
        }
        response = api.post(
            api.cloud_url,
            api.fpl_student_url,
            json_data=dataJson
        )
        print(response)
        logging.info(response)
        print(response.get("code"))
        logging.info(response.get("code"))
        print(response.get("data"))
        logging.info(response.get("data"))
        if (code200 == response.get("code")):
            data = response.get("data")
            print(data)
            logging.info(data)
            rows = data.get("rows")
            print(rows)
            logging.info(rows)
            total = data.get("total")
            print(total)
            logging.info(total)
            localZkh = []
            fplUpLogs = []
            for row in rows:
                zkh = row['zkh']
                examResult = row['examResult']
                result_str = f"{examResult:.0f}"
                mtEquipment = row['mtEquipment']
                resultId = row['resultId']
                gmtStarted = row['gmtStarted']
                studentsDB = StudentDB()
                student1 = studentsDB.get_student_by_zkh_item(zkh, xcxm)
                if student1 is not None:
                    try:
                        studentsDB.update_student(student1['id'],
                                                  {"result": result_str, "mtEquipment": mtEquipment, "status": 1,
                                                   "resultId": resultId, "gmtStarted": gmtStarted})
                        fplUpLog = {"zkh": zkh, "item": xcxm, "result": result_str}
                        fplUpLogs.append(fplUpLog)
                    except Exception as e:
                        print(f"无法添加result属性: {e}")
                        logging.error(f"无法添加result属性: {e}")
                        print(f"student1类型: {type(student1)}")
                        logging.error(f"student1类型: {type(student1)}")
                    print(student1.get("zkh"))
                    logging.info(student1.get("zkh"))
                else:
                    localZkh.append(zkh)
                    total = total - 1
                print(student1)
                logging.info(student1)
            print(fplUpLogs)
            logging.info(fplUpLogs)
            # 修改完成后调用云平台上传提交次数接口
            # response1 = api.post(
            #     api.cloud_url,
            #     api.fpl_student_up_count,
            #     json_data=fplUpLogs
            # )
            # print(response1)
            # print(response1.get("code"))
            warnStr = ""
            if (len(localZkh)):
                warnStr = "准考证号为" + str(localZkh) + "不在本地"
            if warnStr == '':
                return ResponseUtils.build_response(code200, "success",
                                                    "同步成功，同步数量为：" + str(total) + ";" + warnStr)
            else:
                return ResponseUtils.build_response(code1, "warning",
                                                    "同步成功，同步数量为：" + str(total) + ";" + warnStr)
        else:
            return ResponseUtils.build_response(code1, "error", response.get("msg"))
    except Exception as e:
        print(f"云平台接口调用过程中发生错误: {str(e)}")
        logging.error(f"云平台接口调用过程中发生错误: {str(e)}")
        raise


def get_current_timestamp():
    """获取当前时间戳（毫秒级）"""
    return int(datetime.now().timestamp() * 1000)


# 上传本地待上传的数据到第三方
@transaction.atomic
@app.route('/api/sync/local/result/third', methods=['GET'])
def sync_local_result_third():
    # api = ApiClient(config_file="/config/apiconfig.ini")
    api = ApiClient()
    studentsDB = StudentDB()
    # 获取状态为待上传的考生数据
    students = studentsDB.search_students({"status": "1"})
    api._authenticate()
    # 检查数据有效性
    if students is None:
        print("错误: 查询返回了 None")
        logging.info("错误: 查询返回了 None")
        print("没有找到符合条件的学生或查询结果为空")
        logging.info("没有找到符合条件的学生或查询结果为空")
        return ResponseUtils.build_response(code1, "warning", "没有找到符合条件的学生或查询结果为空；")
    elif not students:  # 空列表/字典/集合等
        print("警告: 查询返回了空结果")
        logging.info("警告: 查询返回了空结果")
        print("没有找到符合条件的学生或查询结果为空")
        logging.info("没有找到符合条件的学生或查询结果为空")
        return ResponseUtils.build_response(code1, "warning", "没有找到符合条件的学生或查询结果为空；")
    else:
        total = 0
        # 请求时间，时间戳
        requestTime = get_current_timestamp()
        # 错误码 ：0表示成功，其它均为失败
        msEquipment = 0
        # 加密标识0-不加密，1-加密；只对data加密
        encrypt = 0
        # 版本号
        version = "1.0.0"
        jsonData = {
            "msEquipment": msEquipment,
            "encrypt": encrypt,
            "requestTime": requestTime,
            "version": version,
            "token": api.token,
            "data": []
        }
        # 初始化 data_list（JSON 数组）
        data_list = []
        fplUpLogs = []
        # 尝试遍历
        print("\n开始遍历学生数据:")
        logging.info("\n开始遍历学生数据:")
        for student in students:
            try:
                print("上传开始")
                logging.info("上传开始")
                # 发送成绩给第三方
                # 体测或考试id
                id = student["id"]
                # 体测或考试id
                testId = student["testId"]
                # 学校代码(考点代码)
                siteCode = student["siteCode"]
                # 日程编号-考试使用
                scheduleNo = student["scheduleNo"]
                # 准考证号
                studentCode = student["studentCode"]
                # 项目代码
                itemCode = student["itemCode"]
                # 项目名称
                itemName = student["itemName"]
                # 性别
                gender = student["gender"]
                # 组号-考试使用
                groupNo = student["groupNo"]
                # 组内序号-考试使用
                trackNo = student["trackNo"]
                # 测试轮次顺序号
                # 比如规定测试次数为3；第⼀次测试序号：1，第⼆次测试序号2，第三次测试序号3；
                roundNo = 1
                # 成绩状态：1:正常 2:犯规 3:中退 4:弃权 5:测试-考试使用
                resultStatus = 1
                # 考试状态（0.正常，2.补考）-考试使用
                studentItemStatus = 0
                # 测试用户名
                userInfo = "xuetong"
                # 视频设备信息唯⼀编码，多个用英文逗号分隔
                mtEquipment = student["mtEquipment"]
                # 是否重测：0 否 1 是
                isRetest = "0"
                # 临时组号
                tempGroupNo = student["groupNo"]
                # 临时道号
                tempTrackNo = student["trackNo"]
                # 组别名称
                sortName = student["sortName"]
                # 考试类型: 0.正常 1.缓考
                examType = "0"
                # 成绩
                result = student["result"]
                # 考试记录ID
                resultId = student["resultId"]
                # 考试开始时间
                gmtStarted = student["gmtStarted"]
                if gmtStarted:
                    # 转换为 datetime 对象
                    dt = datetime.strptime(gmtStarted, "%Y-%m-%d %H:%M:%S")
                    # 转换为时间戳（秒级）
                    gmtStartedTamp = int(dt.timestamp())
                else:
                    gmtStartedTamp = requestTime
                data = {
                    "testId": testId,
                    "siteCode": siteCode,
                    "scheduleNo": scheduleNo,
                    "studentCode": studentCode,
                    "itemCode": itemCode,
                    "gender": gender,
                    "testTime": gmtStartedTamp,
                    "groupNo": groupNo,
                    "trackNo": trackNo,
                    "roundNo": roundNo,
                    "resultStatus": resultStatus,
                    "studentItemStatus": studentItemStatus,
                    "userInfo": userInfo,
                    "mtEquipment": mtEquipment,
                    "isRetest": isRetest,
                    "tempGroupNo": tempGroupNo,
                    "tempTrackNo": tempTrackNo,
                    "result": str(result),
                    "examType": examType,
                    "groupType": 2,
                    "sortName": sortName
                }
                data_list.append(data)
                fplUpLog = {"id": id, "zkh": studentCode, "item": itemName, "result": str(result),
                            "resultId": str(resultId)}
                fplUpLogs.append(fplUpLog)
            except Exception as e:
                print(f"组装上传成绩json发生错误: {str(e)}")
                logging.error(f"组装上传成绩json发生错误: {str(e)}")
                raise
        jsonData["data"] = data_list
        print("上传成绩至第三方开始")
        logging.info("上传成绩至第三方开始")
        print("请求参数如下：")
        logging.info("请求参数如下：")
        print(str(jsonData))
        logging.info(str(jsonData))
        response = api.post(
            api.base_url,
            api.upload_result_info,
            json_data=jsonData,
            headers={
                "Authorization": "Bearer " + api.token}
        )
        print(str(response))
        logging.info(str(response))
        print(str(response.get("data")))
        logging.info(str(response.get("data")))
        if 1 == response.get("code"):
            print("考生成绩上传第三方失败，原因如下：")
            logging.info("考生成绩上传第三方失败，原因如下：")
            print(str(response))
            logging.info(str(response))
            return ResponseUtils.build_response(code1, "error", "考生成绩上传第三方失败，原因如下：" + str(response.get("msg")))
        dataStr = None
        if response.get("data") is not None:
            # 创建 AES 加密器
            encryptKey = api.encryptKey.encode('utf-8')
            aes = AesUtils(encryptKey)
            if (str(response.get("data")) == '[]' or response.get("data") is None):
                dataStr = '[]'
            else:
                dataStr = aes.decrypt(response.get("data"))
            print("dataStr：" + dataStr)
            logging.info("dataStr：" + dataStr)
            # print("考生成绩上传第三方失败，原因如下：")
            # print(str(response))
            # return ResponseUtils.build_response(code1, "error", "考生成绩上传第三方失败，原因如下：" + str(response.msg))
        if '[]' == dataStr or response.get("data") is None or dataStr is None:
            print("调用云平台上传提交次数开始")
            logging.info("调用云平台上传提交次数开始")
            print("请求参数如下：")
            logging.info("请求参数如下：")
            print(str(fplUpLogs))
            logging.info(str(fplUpLogs))
            # 修改完成后调用云平台上传提交次数接口
            response1 = api.post(
                api.cloud_url,
                api.fpl_student_up_count,
                json_data=fplUpLogs
            )
            print(response1)
            logging.info(response1)
            print(response1.get("code"))
            logging.info(response1.get("code"))
            if 200 == response1.get("code"):
                for fplUpLog in fplUpLogs:
                    studentsDB.update_student(fplUpLog["id"], {"status": 2})
                    total = total + 1
                return ResponseUtils.build_response(code200, "success", "处理完成，同步总数量：" + str(total))
            else:
                print("调用云平台上传提交次数失败，原因如下：")
                logging.info("调用云平台上传提交次数失败，原因如下：")
                print(str(response1))
                logging.info(str(response1))
                return ResponseUtils.build_response(code1, "error",
                                                    "调用云平台上传提交次数失败，原因如下：" + str(response1.get("msg")))


# 获取组内考生成绩信息
@app.route('/api/print/result', methods=['POST'])
def print_result():
    try:
        # 获取 JSON 请求体
        data = request.get_json()
        if not data:
            return ResponseUtils.build_response(code1, "error", "请求体必须为JSON格式")
        # 从 JSON 中提取参数
        studentCodes = data.get('studentCodes')
        groupNo = data.get('groupNo')
        studentsDB = StudentDB()
        student = studentsDB.get_students_by_zkh_groupNo(groupNo)
        return ResponseUtils.build_response(code200, "success", "查询成功", student)
    except Exception as e:
        print(f"获取组内考生成绩信息中发生错误: {str(e)}")
        logging.error(f"获取组内考生成绩信息中发生错误: {str(e)}")
        raise


if __name__ == '__main__':
    # 自动打开浏览器
    webbrowser.open('http://127.0.0.1:8110')
    app.run(port=8110)